package codeMaker;

import codeMaker.impl.MakeCodeImpl;
import com.sun.org.apache.regexp.internal.REUtil;
import constant.ChildWindowConstant;
import constant.CodeConstant;
import constant.Constant;
import entity.DataSourceModel;
import entity.DatabaseModel;
import org.apache.commons.lang3.StringUtils;

import javax.swing.*;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.util.Map;

/**
 * 多数据源配置
 *
 * @author zrx
 */
public class MutiTableConfig extends JFrame {


	private static MutiTableConfig frame = null;

	private static final String DATA_SOURCE_REGX = "^(?=.{1,10}$)[a-zA-Z]{1,10}\\d{0,10}$";
	/**
	 * serialVersionUID
	 */
	public static final long serialVersionUID = -872842032932282858L;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(() -> {
			try {
				//如果已经打开过了，关闭之前的
				if (frame != null) {
					frame.dispose();
					frame = null;
				}
				frame = new MutiTableConfig();
				frame.setVisible(true);
			} catch (Exception e) {
				e.printStackTrace();
			}
		});
	}

	/**
	 * Create the frame.
	 */
	private MutiTableConfig() {
		//组件
		JPanel contentPane = new JPanel();
		JLabel chooseDataSourceLabel = new JLabel("选择数据源");
		JLabel dataBaseTypeLabel = new JLabel("数据库类型");
		JComboBox<String> dataBaseTypeBox = new JComboBox<>();
		JLabel ipLabel = new JLabel("数据库ip");
		JTextField ipText = new JTextField();
		JLabel portLabel = new JLabel("端口");
		JTextField portText = new JTextField();
		JLabel userNameLabel = new JLabel("用户名");
		JTextField userNameText = new JTextField();
		JLabel pwdLabel = new JLabel("密码");
		JTextField pwdText = new JTextField();
		JLabel databaseNameLabel = new JLabel("数据库名称（SERVICE NAME/SID）");
		JTextField databaseNameText = new JTextField();
		JLabel dataSourceLabel = new JLabel("数据源名称");
		JTextField dataSourceText = new JTextField();
		JComboBox<String> chooseDataSourceBox = new JComboBox<>();
		//获取主界面的dataSourcecBoxModelMain
		DefaultComboBoxModel<String> dataSourcecBoxModelMain = (DefaultComboBoxModel<String>) MakeCodeImpl.getInstance().dataSouceBox.getModel();
		DefaultComboBoxModel<String> dataSourcecBoxModel = new DefaultComboBoxModel<>();
		for (int i = 0; i < dataSourcecBoxModelMain.getSize(); i++) {
			dataSourcecBoxModel.addElement(dataSourcecBoxModelMain.getElementAt(i));
		}
		chooseDataSourceBox.setModel(dataSourcecBoxModel);
		JLabel tableNameLabel = new JLabel("数据表（多个用 # 隔开）");
		JTextField tableNameText = new JTextField();
		tableNameText.setColumns(10);
		JLabel lblNewLabel = new JLabel("<html><body style='color:red'>以上除数据表皆为必填项，配置完之后点击保存即可在主界面选择</body></html>");
		JButton saveSourceBtn = new JButton("保存");
		JButton delBtn = new JButton("删除");

		//配置
		setResizable(true);
		setTitle("数据源配置");
		setIconImage(Toolkit.getDefaultToolkit().getImage(MakeCode.class.getResource(
				"/org/pushingpixels/substance/internal/contrib/randelshofer/quaqua/images/color_wheel.png")));
		setBounds(100, 100, 595, 435);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		dataBaseTypeBox.setModel(new DefaultComboBoxModel<>(new String[]{"mysql", "oracle", "postgresql", "sqlserver"}));
		ipText.setColumns(10);
		portText.setColumns(10);
		userNameText.setColumns(10);
		pwdText.setColumns(10);
		databaseNameText.setColumns(10);
		dataSourceText.setColumns(10);

		//保存listener
		saveSourceBtn.addActionListener(e -> {
			//如果校验不通过
			if (!checkNecessary(ipText, portText, userNameText, pwdText, databaseNameText, dataSourceText)) {
				JOptionPane.showMessageDialog(null, "请把输入框填写完毕 && 数据源名称由字母或数字组成，必须以字母开头，长度不要超过10位", "警告",
						JOptionPane.WARNING_MESSAGE);
				return;
			}
			//如果已经存在该数据源
			String dataSourceName = dataSourceText.getText();
			if (ChildWindowConstant.dataSourceModelMap.containsKey(dataSourceName)) {
				//如果不覆盖，直接return
				if (JOptionPane.showConfirmDialog(null,
						"该数据源已存在，是否覆盖？覆盖后原来配置的数据项等信息将自动失效，需要重新配置！",
						"提示", JOptionPane.YES_NO_OPTION) != 0) {
					return;
				}
			}
			//设置数据源信息并添加到全局变量
			DataSourceModel dataSourceModel = new DataSourceModel();
			dataSourceModel.setDataSourceName(dataSourceName);
			dataSourceModel.setDataBaseTypeVal((String) dataBaseTypeBox.getSelectedItem());
			dataSourceModel.setDataBaseIpVal(ipText.getText());
			dataSourceModel.setDataBasePortVal(portText.getText());
			dataSourceModel.setDataBasePwdVal(pwdText.getText());
			dataSourceModel.setDataBaseNameVal(databaseNameText.getText());
			dataSourceModel.setDataBaseUserNameVal(userNameText.getText());
			String tableName = tableNameText.getText();
			for (Map.Entry<String, DataSourceModel> entry : ChildWindowConstant.dataSourceModelMap.entrySet()) {
				String sourceName = entry.getKey();
				DataSourceModel model = entry.getValue();
				String modelTableName = model.getTableName();
				String[] modelTableNameArr = modelTableName.split("#");
				String[] tableNameArr = tableName.split("#");
				//如果不是自己
				if (!sourceName.equals(dataSourceName)) {
					for (String name : tableNameArr) {
						for (String modelName : modelTableNameArr) {
							//如果发现不同的数据源有配置的相同的表，给予提示
							if (name.equals(modelName)) {
								JOptionPane.showMessageDialog(null, "数据源 " + sourceName + " 中已经配置了 " + name + " 表，暂不支持不同数据源配置相同名称的表" + CodeConstant.NEW_LINE + CodeConstant.NEW_LINE +
												"猜测您是想配置多数据源主从读写分离，在代码生成后直接修改对应 service 层的 @DBType 注解即可动态选择方法执行主库或从库，所以只需要配置主数据源的表即可" + CodeConstant.NEW_LINE + CodeConstant.NEW_LINE +
												"也可以通过修改 DynamicDataSourceAspect 切面来定制数据源的个性化切换！", "提示",
										JOptionPane.WARNING_MESSAGE);
								return;
							}
						}
					}
				}
			}
			dataSourceModel.setTableName(tableName);
			//放入全局变量
			ChildWindowConstant.dataSourceModelMap.put(dataSourceName, dataSourceModel);
			//先移除，再添加
			dataSourcecBoxModel.removeElement(dataSourceName);
			dataSourcecBoxModel.addElement(dataSourceName);
			dataSourcecBoxModelMain.removeElement(dataSourceName);
			dataSourcecBoxModelMain.addElement(dataSourceName);
			JOptionPane.showMessageDialog(null, "保存成功！", "提示",
					JOptionPane.INFORMATION_MESSAGE);
		});

		//数据源下拉listener
		chooseDataSourceBox.addItemListener(e -> {
			if (e.getStateChange() != ItemEvent.SELECTED) {
				return;
			}
			String dataSoucrce = (String) chooseDataSourceBox.getSelectedItem();
			//如果选择请选择
			if (CodeConstant.PLEASE_CHOOSE.equals(dataSoucrce)) {
				ipText.setText("");
				dataBaseTypeBox.setSelectedItem("mysql");
				portText.setText("");
				userNameText.setText("");
				pwdText.setText("");
				databaseNameText.setText("");
				dataSourceText.setText("");
				tableNameText.setText("");
				return;
			}
			DataSourceModel dataSourceModel = ChildWindowConstant.dataSourceModelMap.get(dataSoucrce);
			ipText.setText(dataSourceModel.getDataBaseIpVal());
			dataBaseTypeBox.setSelectedItem(dataSourceModel.getDataBaseTypeVal());
			portText.setText(dataSourceModel.getDataBasePortVal());
			userNameText.setText(dataSourceModel.getDataBaseUserNameVal());
			pwdText.setText(dataSourceModel.getDataBasePwdVal());
			databaseNameText.setText(dataSourceModel.getDataBaseNameVal());
			dataSourceText.setText(dataSourceModel.getDataSourceName());
			tableNameText.setText(dataSourceModel.getTableName());
		});

		/**
		 * 删除监听器
		 */
		delBtn.addActionListener(e -> {
			String dataSoucrce = (String) chooseDataSourceBox.getSelectedItem();
			if (CodeConstant.PLEASE_CHOOSE.equals(dataSoucrce)) {
				JOptionPane.showMessageDialog(null, "请选择需要删除的数据源再进行删除！", "警告",
						JOptionPane.WARNING_MESSAGE);
				return;
			}
			dataSourcecBoxModel.removeElement(dataSoucrce);
			dataSourcecBoxModelMain.removeElement(dataSoucrce);
			//删除全局变量
			ChildWindowConstant.dataSourceModelMap.remove(dataSoucrce);
			JOptionPane.showMessageDialog(null, "删除成功！", "提示",
					JOptionPane.INFORMATION_MESSAGE);
		});


		//样式
		GroupLayout glContentPane = new GroupLayout(contentPane);
		glContentPane.setHorizontalGroup(
				glContentPane.createParallelGroup(Alignment.TRAILING)
						.addGroup(glContentPane.createSequentialGroup()
								.addGap(154)
								.addComponent(saveSourceBtn, GroupLayout.PREFERRED_SIZE, 91, GroupLayout.PREFERRED_SIZE)
								.addPreferredGap(ComponentPlacement.RELATED)
								.addComponent(delBtn, GroupLayout.PREFERRED_SIZE, 91, GroupLayout.PREFERRED_SIZE)
								.addContainerGap(227, Short.MAX_VALUE))
						.addGroup(glContentPane.createSequentialGroup()
								.addContainerGap()
								.addGroup(glContentPane.createParallelGroup(Alignment.LEADING)
										.addComponent(lblNewLabel, GroupLayout.DEFAULT_SIZE, 445, Short.MAX_VALUE)
										.addGroup(glContentPane.createSequentialGroup()
												.addComponent(tableNameLabel)
												.addPreferredGap(ComponentPlacement.RELATED)
												.addComponent(tableNameText, GroupLayout.DEFAULT_SIZE, 304, Short.MAX_VALUE))
										.addGroup(glContentPane.createSequentialGroup()
												.addGroup(glContentPane.createParallelGroup(Alignment.LEADING)
														.addGroup(glContentPane.createSequentialGroup()
																.addGroup(glContentPane.createParallelGroup(Alignment.LEADING)
																		.addGroup(glContentPane.createSequentialGroup()
																				.addComponent(ipLabel)
																				.addPreferredGap(ComponentPlacement.RELATED)
																				.addComponent(ipText, GroupLayout.PREFERRED_SIZE, 78, GroupLayout.PREFERRED_SIZE)
																				.addGap(18)
																				.addComponent(portLabel))
																		.addGroup(glContentPane.createSequentialGroup()
																				.addComponent(chooseDataSourceLabel)
																				.addPreferredGap(ComponentPlacement.RELATED)
																				.addComponent(chooseDataSourceBox, GroupLayout.PREFERRED_SIZE, 97, GroupLayout.PREFERRED_SIZE)))
																.addPreferredGap(ComponentPlacement.RELATED)
																.addGroup(glContentPane.createParallelGroup(Alignment.LEADING)
																		.addGroup(glContentPane.createSequentialGroup()
																				.addGap(4)
																				.addComponent(portText, GroupLayout.PREFERRED_SIZE, 46, GroupLayout.PREFERRED_SIZE)
																				.addGap(29)
																				.addComponent(userNameLabel)
																				.addPreferredGap(ComponentPlacement.RELATED)
																				.addComponent(userNameText, GroupLayout.PREFERRED_SIZE, 48, GroupLayout.PREFERRED_SIZE)
																				.addPreferredGap(ComponentPlacement.RELATED, 31, Short.MAX_VALUE)
																				.addComponent(pwdLabel)
																				.addGap(4))
																		.addGroup(glContentPane.createSequentialGroup()
																				.addGap(24)
																				.addComponent(dataBaseTypeLabel)
																				.addPreferredGap(ComponentPlacement.RELATED)
																				.addComponent(dataBaseTypeBox, GroupLayout.PREFERRED_SIZE, 97, GroupLayout.PREFERRED_SIZE))))
														.addGroup(glContentPane.createSequentialGroup()
																.addComponent(databaseNameLabel)
																.addPreferredGap(ComponentPlacement.RELATED)
																.addComponent(databaseNameText, GroupLayout.PREFERRED_SIZE, 55, GroupLayout.PREFERRED_SIZE)
																.addGap(27)
																.addComponent(dataSourceLabel)
																.addPreferredGap(ComponentPlacement.RELATED)
																.addComponent(dataSourceText, GroupLayout.PREFERRED_SIZE, 52, GroupLayout.PREFERRED_SIZE)))
												.addPreferredGap(ComponentPlacement.UNRELATED)
												.addComponent(pwdText, GroupLayout.PREFERRED_SIZE, 47, GroupLayout.PREFERRED_SIZE)
												.addPreferredGap(ComponentPlacement.RELATED)))
								.addGap(127))
		);
		glContentPane.setVerticalGroup(
				glContentPane.createParallelGroup(Alignment.LEADING)
						.addGroup(glContentPane.createSequentialGroup()
								.addGap(18)
								.addGroup(glContentPane.createParallelGroup(Alignment.BASELINE)
										.addComponent(chooseDataSourceLabel)
										.addComponent(chooseDataSourceBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
										.addComponent(dataBaseTypeLabel)
										.addComponent(dataBaseTypeBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
								.addGap(18)
								.addGroup(glContentPane.createParallelGroup(Alignment.BASELINE)
										.addComponent(ipLabel)
										.addComponent(pwdLabel)
										.addComponent(ipText, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
										.addComponent(pwdText, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
										.addComponent(portLabel)
										.addComponent(portText, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
										.addComponent(userNameLabel)
										.addComponent(userNameText, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
								.addGap(18)
								.addGroup(glContentPane.createParallelGroup(Alignment.BASELINE)
										.addComponent(databaseNameLabel)
										.addComponent(dataSourceLabel)
										.addComponent(dataSourceText, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
										.addComponent(databaseNameText, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
								.addGap(18)
								.addGroup(glContentPane.createParallelGroup(Alignment.BASELINE)
										.addComponent(tableNameLabel)
										.addComponent(tableNameText, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
								.addGap(18)
								.addComponent(lblNewLabel)
								.addGap(18)
								.addGroup(glContentPane.createParallelGroup(Alignment.BASELINE)
										.addComponent(saveSourceBtn)
										.addComponent(delBtn))
								.addContainerGap(154, Short.MAX_VALUE))
		);
		contentPane.setLayout(glContentPane);
	}

	/**
	 * 检查参数是否完整
	 *
	 * @return
	 */
	private boolean checkNecessary(JTextField ipText, JTextField portText, JTextField userNameText, JTextField pwdText, JTextField databaseNameText, JTextField dataSourceText) {
		if (StringUtils.isEmpty(ipText.getText())
				|| StringUtils.isEmpty(portText.getText()) || StringUtils.isEmpty(userNameText.getText())
				|| StringUtils.isEmpty(pwdText.getText()) || StringUtils.isEmpty(databaseNameText.getText())
				|| StringUtils.isEmpty(dataSourceText.getText())) {
			return false;
		}
		//检查数据源名称是否由英文和数字组成
		return dataSourceText.getText().matches(DATA_SOURCE_REGX);
	}
}
